package com.wenx.v3system.modular.cloud.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wenx.v3core.error.BusinessException;
import com.wenx.v3system.modular.cloud.domain.dto.SysTeamDto;
import com.wenx.v3system.modular.cloud.domain.dto.SysUserDto;
import com.wenx.v3system.modular.cloud.domain.maps.SysTeamMap;
import com.wenx.v3system.modular.cloud.domain.maps.SysUserMap;
import com.wenx.v3system.modular.cloud.domain.po.SysTeam;
import com.wenx.v3system.modular.cloud.domain.po.SysUser;
import com.wenx.v3system.modular.cloud.domain.query.SysTeamQuery;
import com.wenx.v3system.modular.cloud.mapper.SysTeamMapper;
import com.wenx.v3system.modular.cloud.service.SysTeamRestService;
import com.wenx.v3system.modular.cloud.service.SysUserRestService;
import com.wenx.v3system.modular.cloud.service.SysUserTeamService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 系统团队服务实现类
 * 基于Enhanced RBAC权限模型
 * 提供团队管理、成员管理和角色分配功能
 *
 * @author wenx
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
public class SysTeamRestServiceImpl extends ServiceImpl<SysTeamMapper, SysTeam>
        implements SysTeamRestService {

    private final SysUserTeamService sysUserTeamService;
    private final SysUserRestService sysUserService;

    // 缓存常量
    private static final String TEAM_CACHE = "sys:team";
    private static final String TEAM_TREE_CACHE = "sys:team:tree";
    private static final String USER_TEAMS_CACHE = "sys:user:teams";
    private static final String TEAM_MEMBERS_CACHE = "sys:team:members";

    @Override
    public IPage<?> page(SysTeamQuery query) {
        LambdaQueryWrapper<SysTeam> wrapper = new LambdaQueryWrapper<SysTeam>()
                .eq(SysTeam::getDeleted, false)
                .like(StringUtils.hasText(query.getName()), SysTeam::getName, query.getName())
                .like(StringUtils.hasText(query.getCode()), SysTeam::getCode, query.getCode())
                .eq(query.getStatus() != null, SysTeam::getStatus, query.getStatus())
                .eq(query.getDepartmentId() != null, SysTeam::getDepartmentId, query.getDepartmentId())
                .like(StringUtils.hasText(query.getKeyword()), SysTeam::getName, query.getKeyword())
                .or(StringUtils.hasText(query.getKeyword()))
                .like(StringUtils.hasText(query.getKeyword()), SysTeam::getCode, query.getKeyword())
                .orderByDesc(SysTeam::getCreateTime);

        IPage<SysTeam> result = super.page(new Page<>(query.getCurrent(), query.getSize()), wrapper);
        return result.convert(this::convertToDto);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {TEAM_CACHE, TEAM_TREE_CACHE, USER_TEAMS_CACHE}, allEntries = true)
    public void add(SysTeamDto dto) {
        if (checkTeamCode(dto.getCode(), null)) {
            throw new BusinessException("团队编码已存在: " + dto.getCode());
        }

        SysTeam team = SysTeamMap.INSTANCE.toPo(dto);
        if (!super.save(team)) {
            throw new BusinessException("团队新增失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {TEAM_CACHE, TEAM_TREE_CACHE, USER_TEAMS_CACHE, TEAM_MEMBERS_CACHE}, allEntries = true)
    public void delete(Serializable id) {
        if (id == null) {
            throw new BusinessException("团队ID不能为空");
        }

        SysTeam team = super.getById(id);
        if (team == null) {
            throw new BusinessException("团队不存在，ID: " + id);
        }

        // 删除团队成员关联（子表）
        sysUserTeamService.removeTeamUsers(Long.parseLong(id.toString()));

        // 删除团队（主表）
        boolean success = super.removeById(id);
        if (!success) {
            throw new BusinessException("团队删除失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {TEAM_CACHE, TEAM_TREE_CACHE, USER_TEAMS_CACHE}, allEntries = true)
    public void update(SysTeamDto dto) {
        if (dto.getId() == null) {
            throw new BusinessException("团队ID不能为空");
        }

        SysTeam existingTeam = super.getById(dto.getId());
        if (existingTeam == null) {
            throw new BusinessException("团队不存在，ID: " + dto.getId());
        }

        if (checkTeamCode(dto.getCode(), dto.getId())) {
            throw new BusinessException("团队编码已存在: " + dto.getCode());
        }

        // 使用MapStruct映射器进行转换，确保状态字段正确转换
        SysTeam teamToUpdate = SysTeamMap.INSTANCE.toPo(dto);
        this.updateBySelect(teamToUpdate);
    }

    @Override
    @Cacheable(value = TEAM_CACHE, key = "#id")
    public Object get(Serializable id) {
        SysTeam team = super.getById(id);
        return team != null ? convertToDto(team) : null;
    }


    @Override
    @Cacheable(value = USER_TEAMS_CACHE, key = "#userId")
    public List<SysTeamDto> getUserTeams(Long userId) {
        if (userId == null) {
            throw new BusinessException("用户ID不能为空");
        }

        List<Long> teamIds = sysUserTeamService.getTeamIdsByUserId(userId);
        if (ObjectUtil.isEmpty(teamIds)) {
            return Collections.emptyList();
        }

        LambdaQueryWrapper<SysTeam> wrapper = new LambdaQueryWrapper<SysTeam>()
                .in(SysTeam::getId, teamIds)
                .eq(SysTeam::getDeleted, false)
                .eq(SysTeam::getStatus, 1)
                .orderByAsc(SysTeam::getSort);

        List<SysTeam> teams = super.list(wrapper);
        return teams.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    @Override
    @Cacheable(value = TEAM_MEMBERS_CACHE, key = "#teamId")
    public List<Long> getTeamMembers(Long teamId) {
        if (teamId == null) {
            throw new BusinessException("团队ID不能为空");
        }
        return sysUserTeamService.getUserIdsByTeamId(teamId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {TEAM_MEMBERS_CACHE, USER_TEAMS_CACHE}, allEntries = true)
    public void addTeamMembers(Long teamId, List<Long> userIds) {
        if (teamId == null) {
            throw new BusinessException("团队ID不能为空");
        }
        if (CollectionUtils.isEmpty(userIds)) {
            throw new BusinessException("用户ID列表不能为空");
        }

        // 检查团队是否存在
        SysTeam team = super.getById(teamId);
        if (team == null) {
            throw new BusinessException("团队不存在，ID: " + teamId);
        }

        // 批量检查用户是否存在
        List<SysUser> existingUsers = sysUserService.listByIds(userIds);
        if (existingUsers.size() != userIds.size()) {
            List<Long> existingUserIds = existingUsers.stream()
                    .map(SysUser::getId)
                    .toList();
            List<Long> notFoundUserIds = userIds.stream()
                    .filter(id -> !existingUserIds.contains(id))
                    .toList();
            throw new BusinessException("用户不存在，ID: " + notFoundUserIds);
        }

        // 批量添加团队成员，只添加不在团队中的用户
        List<Long> usersToAdd = userIds.stream()
                .filter(userId -> !sysUserTeamService.isUserInTeam(userId, teamId))
                .toList();

        if (!usersToAdd.isEmpty()) {
            // 为每个用户分配团队
            for (Long userId : usersToAdd) {
                sysUserTeamService.assignTeamsToUser(userId, List.of(teamId));
            }
        }
    }

    /**
     * 批量删除团队
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {TEAM_CACHE, TEAM_TREE_CACHE, USER_TEAMS_CACHE, TEAM_MEMBERS_CACHE}, allEntries = true)
    public void batchDelete(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new BusinessException("团队ID列表不能为空");
        }

        for (Long id : ids) {
            delete(id);
        }
    }

    /**
     * 分页获取团队成员
     */
    @Override
    @Cacheable(value = TEAM_MEMBERS_CACHE, key = "'page:' + #teamId + ':' + #current + ':' + #size + ':' + (#keyword != null ? #keyword : '')")
    public Object getTeamMembersPage(Long teamId, Integer current, Integer size, String keyword) {
        if (teamId == null) {
            throw new BusinessException("团队ID不能为空");
        }

        // 设置默认分页参数
        int pageNum = current != null ? current : 1;
        int pageSize = size != null ? size : 10;

        // 获取团队成员用户ID列表
        List<Long> userIds = sysUserTeamService.getUserIdsByTeamId(teamId);

        if (CollectionUtils.isEmpty(userIds)) {
            return Map.of(
                    "records", List.of(),
                    "totalElements", 0,
                    "totalPages", 0,
                    "size", pageSize,
                    "number", pageNum - 1,
                    "first", true,
                    "last", true
            );
        }

        // 构建用户查询条件
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<SysUser>()
                .in(SysUser::getId, userIds)
                .eq(SysUser::getDeleted, false);

        // 添加关键词搜索条件
        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w.like(SysUser::getUsername, keyword)
                    .or().like(SysUser::getRealName, keyword)
                    .or().like(SysUser::getEmail, keyword));
        }

        wrapper.orderByDesc(SysUser::getCreateTime);

        // 执行分页查询
        Page<SysUser> page = new Page<>(pageNum, pageSize);
        IPage<SysUser> result = sysUserService.page(page, wrapper);

        // 转换为DTO
        List<SysUserDto> userDtos = result.getRecords().stream()
                .map(this::convertUserToDto)
                .collect(Collectors.toList());

        return Map.of(
                "records", userDtos,
                "totalElements", result.getTotal(),
                "totalPages", result.getPages(),
                "size", result.getSize(),
                "number", result.getCurrent() - 1,
                "first", result.getCurrent() == 1,
                "last", result.getCurrent() == result.getPages()
        );
    }


    public boolean checkTeamCode(String code, Long excludeId) {
        if (!StringUtils.hasText(code)) {
            return false;
        }

        LambdaQueryWrapper<SysTeam> wrapper = new LambdaQueryWrapper<SysTeam>()
                .eq(SysTeam::getCode, code)
                .eq(SysTeam::getDeleted, false)
                .ne(excludeId != null, SysTeam::getId, excludeId);

        return super.count(wrapper) > 0;
    }

    @Override
    @Cacheable(value = TEAM_TREE_CACHE, key = "'tree:' + (#parentId != null ? #parentId : 'root')")
    public List<SysTeamDto> getTeamTree(Long parentId) {
        List<SysTeamDto> childTeams = getChildTeams(parentId);

        // 递归构建子团队树
        for (SysTeamDto team : childTeams) {
            List<SysTeamDto> children = getTeamTree(team.getId());
            team.setChildren(children);
        }

        return childTeams;
    }


    public List<SysTeamDto> getChildTeams(Long parentId) {
        if (parentId == null) {
            return Collections.emptyList();
        }

        LambdaQueryWrapper<SysTeam> wrapper = new LambdaQueryWrapper<SysTeam>();
        wrapper.eq(SysTeam::getParentId, parentId)
                .eq(SysTeam::getDeleted, false)
                .orderByAsc(SysTeam::getSort);

        List<SysTeam> teams = super.list(wrapper);
        return teams.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {TEAM_MEMBERS_CACHE, USER_TEAMS_CACHE}, allEntries = true)
    public void removeTeamMembers(Long teamId, List<Long> userIds) {
        if (teamId == null) {
            throw new BusinessException("团队ID不能为空");
        }
        if (CollectionUtils.isEmpty(userIds)) {
            throw new BusinessException("用户ID列表不能为空");
        }

        // 检查团队是否存在
        SysTeam team = super.getById(teamId);
        if (team == null) {
            throw new BusinessException("团队不存在，ID: " + teamId);
        }

        // 批量检查用户是否存在
        List<SysUser> existingUsers = sysUserService.listByIds(userIds);
        if (existingUsers.size() != userIds.size()) {
            List<Long> existingUserIds = existingUsers.stream()
                    .map(SysUser::getId)
                    .collect(Collectors.toList());
            List<Long> notFoundUserIds = userIds.stream()
                    .filter(id -> !existingUserIds.contains(id))
                    .collect(Collectors.toList());
            throw new BusinessException("用户不存在，ID: " + notFoundUserIds);
        }

        // 批量移除团队成员，只移除在团队中的用户
        List<Long> usersToRemove = userIds.stream()
                .filter(userId -> sysUserTeamService.isUserInTeam(userId, teamId))
                .collect(Collectors.toList());

        if (!usersToRemove.isEmpty()) {
            // 获取每个用户当前的团队列表，移除指定团队后重新分配
            for (Long userId : usersToRemove) {
                List<Long> currentTeamIds = sysUserTeamService.getTeamIdsByUserId(userId);
                List<Long> newTeamIds = currentTeamIds.stream()
                        .filter(id -> !id.equals(teamId))
                        .collect(Collectors.toList());

                // 先清除用户所有团队关系，再重新分配剩余团队
                sysUserTeamService.removeUserTeams(userId);
                if (!newTeamIds.isEmpty()) {
                    sysUserTeamService.assignTeamsToUser(userId, newTeamIds);
                }
            }
        }
    }

    @Override
    public List<SysTeamDto> getAvailableTeams(Long userId) {
        if (userId == null) {
            throw new BusinessException("用户ID不能为空");
        }

        // 获取用户已加入的团队ID列表
        List<Long> joinedTeamIds = sysUserTeamService.getTeamIdsByUserId(userId);

        LambdaQueryWrapper<SysTeam> wrapper = new LambdaQueryWrapper<SysTeam>()
                .eq(SysTeam::getDeleted, false)
                .eq(SysTeam::getStatus, 1)
                .notIn(!ObjectUtil.isEmpty(joinedTeamIds), SysTeam::getId, joinedTeamIds)
                .orderByAsc(SysTeam::getSort)
                .orderByDesc(SysTeam::getCreateTime);

        List<SysTeam> teams = super.list(wrapper);
        return teams.stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    /**
     * 转换PO到DTO
     */
    private SysTeamDto convertToDto(SysTeam team) {
        if (team == null) {
            return null;
        }
        SysTeamDto dto = SysTeamMap.INSTANCE.toDto(team);
        // 获取团队成员数量
        List<Long> memberIds = sysUserTeamService.getUserIdsByTeamId(team.getId());
        dto.setMemberCount(memberIds != null ? memberIds.size() : 0);
        return dto;
    }

    /**
     * 转换用户PO到DTO
     */
    private SysUserDto convertUserToDto(SysUser user) {
        if (user == null) {
            return null;
        }
        return SysUserMap.INSTANCE.toDto(user);
    }
}